<?php
namespace Illuminate\Foundation\Http;

use Illuminate\Http\Request;

use Illuminate\Contracts\Validation\ValidatesWhenResolved;

use Illuminate\Validation\ValidatesWhenResolvedTrait;

use Illuminate\Routing\Redirector;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;

class FormRequest extends Request implements ValidatesWhenResolved {
    use ValidatesWhenResolvedTrait;

    protected $container;
    protected $redirector;
    protected $redirect;
    protected $redirectRoute;
    protected $redirectAction;
    protected $errorBag = 'default';

    protected function getValidatorInstance() {
        $factory = $this->container->make(ValidationFactory::class);

        if ( method_exists($this, 'validator') ) {
            $validator = $this->container->call([$this, 'validator'], compact('factory'));
        } else {
            $validator = $this->createDefaultValidator($factory);
        }

        if ( method_exists($this, 'withValidator') ) $this->withValidator($validator);

        return $validator;
    }
    protected function createDefaultValidator(ValidationFactory $factory) {
        return $factory->make(
            $this->validationData(), $this->container->call([$this, 'rules']),
            $this->messages(), $this->attributes()
        );
    }
    protected function validationData() {
        return $this->all();
    }
    protected function failedValidation(Validator $validator) {
        throw (new ValidationException($validator))
            ->errorBag($this->errorBag)
            ->redirectTo($this->getRedirectUrl());
    }
    protected function getRedirectUrl() { // 跳转地址
        $url = $this->redirector->getUrlGenerator();

        if ( $this->redirect ) {
            return $url->to($this->redirect);
        } elseif ( $this->redirectRoute ) {
            return $url->route($this->redirectRoute);
        } elseif ( $this->redirectAction ) {
            return $url->action($this->redirectAction);
        }

        return $url->previous();
    }
    protected function passesAuthorization() {
        if (method_exists($this, 'authorize')) {
            return $this->container->call([$this, 'authorize']);
        }

        return false;
    }
    protected function failedAuthorization() {
        throw new AuthorizationException('This action is unauthorized.');
    }
    public function validated() {
        $rules = $this->container->call([$this, 'rules']);

        return $this->only(collect($rules)->keys()->map(function ($rule) {
            return explode('.', $rule)[0];
        })->unique()->toArray());
    }

    public function messages() { // 消息
        return [];
    }
    public function attributes() { // 规则
        return [];
    }
    public function setRedirector(Redirector $redirector) {
        $this->redirector = $redirector;

        return $this;
    }
    public function setContainer(Container $container) {
        $this->container = $container;

        return $this;
    }
}
